package mmc.server.shell.ops.function;

import mmc.server.shell.Shell;
import mmc.server.shell.ShellException;
import mmc.server.shell.ops.Constant;
import mmc.server.shell.ops.Function;
import mmc.server.shell.ops.LeftAssociativeOperation;
import mmc.server.shell.ops.Operation;

public class Help extends Constant {

    public Help(String text) throws ShellException {
    	super(text, "help");
    }

    @Override
    public double execute() {
    	throw new RuntimeException(this+" has no double output!");
    }
    
    @Override
    public Object executeComplex(){
    	Shell.out.println("+-------------------- associative property (left, right)");
    	Shell.out.println("|+------------------- type (function, constant, operator)");
    	Shell.out.println("|| +----------------- name");
    	Shell.out.println("|| |               +- description");
    	
    	for(Class<? extends Operation> c : Shell.operations){
   			printDescLine(c);
    	}
        
    	return null;
    }
    
    @Override
    public Class<?> getOutputType(){
    	return void.class;
    }
    
    private void printDescLine(Class<? extends Operation> clasz){
    	boolean hide=false;
    	
    	try{
    		hide = (Boolean)clasz.getMethod("hideInDescription").invoke(null);
    	}catch(Exception e){}
    	
    	if(!hide){
    		Shell.out.print(LeftAssociativeOperation.class.isAssignableFrom(clasz)?"L":"R");
    		Shell.out.print(isFunction(clasz)?"F":(isConstant(clasz)?"C":"O"));
    		Shell.out.println(" "+toString(clasz));
    	}
    }
    
    private boolean isFunction(Class<? extends Operation> clasz){
    	return Function.class.isAssignableFrom(clasz);
    }
    
    private boolean isConstant(Class<? extends Operation> clasz){
    	return Constant.class.isAssignableFrom(clasz);
    }
    
    private String toString(Class<? extends Operation> clasz){
    	try{
    		return (String)clasz.getMethod("getDescription").invoke(null);
    	}catch(Exception e){}
    	
    	return clasz.getSimpleName();
    }
    
    public static boolean hideInDescription(){
    	return true;
    }
    
    public static String getDescription(){
    	return formatHelpString("Help","prints this help");
    }
}